import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.Console;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class ChatClient {
	boolean connected = false;
	Socket connection;
	ExecutorService executor;
	String userName;
	String chatName = "You";

	BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
	PrintWriter socketWriter = null;
	BufferedReader socketReader = null;
	InetAddress serverip;
	
	public ChatClient(String name, InetAddress serverip){
		userName = name;
		executor = Executors.newFixedThreadPool(2);
		this.serverip = serverip;
		try {
			Socket s = new Socket(serverip, 5555);
			int port = Integer.parseInt(new BufferedReader(new InputStreamReader(s.getInputStream())).readLine());
			s.setReuseAddress(true);
			s.close();
			s=null;
			ServerSocket serv = new ServerSocket(port);
			Socket sock = serv.accept();
			setSocket(sock);
			socketWriter.println(userName);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.err.println("Failed to connect to server");
			e.printStackTrace();
			System.exit(-1);
		}
		
		new Thread(new SocketListener()).start();
		new Thread(new ConsoleListener()).start();
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		if(args.length < 2){
			System.err.println("Name and Server IP as argument");
			return;
		}
		try {
			new ChatClient(args[0], InetAddress.getByName(args[1]));
		} catch (UnknownHostException e) {
			System.err.println("Invalid Server IP");
			return;
		}
	}

	private class SocketListener implements Runnable {

		public SocketListener(){
		}

		public void run() {
			try {
				//Socket socket
				while(true){
					if(!connected){
						String in = socketReader.readLine();
						if(in!=null){
							System.out.println(in);
						} else {
							System.out.println("Connection aborted");
							System.exit(0);
						}
						String chatstart = "Chat started with ";
						if(in.startsWith(chatstart)){
							connected = true;
							chatName = in.substring(chatstart.length());
						}
						if(in.equals("Username not available")){
							connection.close();
							System.exit(0);
						}
					} else{
						String in = socketReader.readLine();
						if(in==null){
							System.out.println("Connection aborted");
							connection.close();
							System.exit(0);
						}
						System.out.print("\r"+chatName+": "+in+"\n"+userName+": ");
					}
				}
			} catch (SocketException e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}

	private class ConsoleListener implements Runnable {

		public ConsoleListener(){
		}

		public void run() {
			while(true){
				try{
					String line;
					if(connected){
						System.out.print(userName+": ");
						line = consoleReader.readLine();
					} else {
						line = readLineStopWhenConnected();
						if(line==null){
							continue;
						}
					}
					if(line.equalsIgnoreCase("exit")){
						socketWriter.println("exit");
						connection.close();
						return;
					}
					socketWriter.println(line);
				}catch (UnknownHostException eh) {
					// TODO: handle exception
					System.err.println("bad IP");
				} catch (IOException e) {
					// TODO Auto-generated catch block
					System.err.println("Failed to read");
				}

			}

		}
		
		private String readLineStopWhenConnected() throws IOException {
			while(!consoleReader.ready()){
				if(connected){
					return null;
				}
			}
			return consoleReader.readLine();
		}

	}

	/*
	 * 
	 * @param socket
	 */
	public void setSocket(Socket socket) {
		//Skapa ny socket connection med ip från socket och port från socket.in
		//skicka ip som ska kontaktas.

		connection = socket;
		try {
			socketWriter = new PrintWriter(connection.getOutputStream(),true);
			socketReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
